/*
 *  Copyright 2007-2008 by Matthias Buch-Kromann <mbk.isv@cbs.dk>.
 *  *
 *  This file is part of the Open-source Dependency Toolkit (OSDT),
 *  see http://code.google.com/p/open-source-dependency-toolkit.
 *  
 *  The OSDT is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as 
 *  published by the Free Software Foundation, either version 3 of 
 *  the License, or (at your option) any later version.
 * 
 *  The OSDT is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public 
 *  License along with the OSDT in the files COPYING and COPYING.LESSER.
 *  If not, see http://www.gnu.org/licenses.
 */

package org.osdtsystem.graphs.views;

import java.util.Random;
import org.osdtsystem.exceptions.NonUniqueNameException;
import org.osdtsystem.graphs.Graph;
import org.osdtsystem.graphs.GraphEngine;
import org.osdtsystem.values.Layer;
import org.osdtsystem.values.NodeID;

/**
 *
 * @author Matthias Buch-Kromann <mbk.isv@cbs.dk>
 */
public class RandomDependencyAlignment {
    // The number of strongly connected components in a synchronous component
    double[] choiceSCCinSynchronous = {0, 0.5, 0.4, 0.1};
    
    // The number of nodes in a source or target component in an scc
    double[] choiceNodesInScc = {0, 0.1, 0.3, 0.2, 0.2};
    
    // The chance of a double alignment
    double choiceDoubleAlignment = 0.1;
    
    // Random number generator
    Random random = new Random(101172);
    
    // Variables
    public GraphEngine graph;
    public NodeCollection sourceNodes, targetNodes;
    public WordAlignment wordAlignment, goldSccAlignment, goldSynchronousAlignment;
    public NodeID stop, ttop;
    public DependencyTree sourceTree, targetTree;
    public DependencyAlignment dependencyAlignment;
    
    public Layer tunitLayer;
    public Layer sccLayer;
    public Layer sourceLayer, targetLayer;
    
    /*public Map<Node,Node> scc = new HashMap<Node,Node>();
    public Map<Node,Node> stree = new HashMap<Node,Node>();
    public Map<Node,Node> ttree = new HashMap<Node,Node>();
    public Map<Node,Set<Node>> alignments = new HashMap<Node,Set<Node>>();*/
    
    /**
     * 
     * @param graph
     * @param maxnodes
     */
    public RandomDependencyAlignment(GraphEngine graph, int maxnodes) throws NonUniqueNameException {
        // Create source and target nodes
        sourceNodes = new NodeCollectionEngine(graph, "source");
        targetNodes = new NodeCollectionEngine(graph, "target");
        
        // Create word alignments
        wordAlignment = new WordAlignmentEngine(graph, 
                sourceNodes, targetNodes, "word alignment");
        goldSccAlignment = new WordAlignmentEngine(graph, 
                sourceNodes, targetNodes, "gold scc alignment");
        goldSynchronousAlignment = new WordAlignmentEngine(graph, 
                sourceNodes, targetNodes, "gold synchronous alignment");

        // Create source and target dependency trees
        stop = sourceNodes.addNode();
        ttop = targetNodes.addNode();
        sourceTree = new DependencyTreeEngine(graph, sourceNodes, stop, "source tree");
        targetTree = new DependencyTreeEngine(graph, targetNodes, ttop, "target tree");
        
        // Create dependency alignment
        dependencyAlignment = new DependencyAlignmentEngine(graph, 
                sourceTree, targetTree, wordAlignment, "dependency alignment");
        
        // Recursively create the random dependency alignment
        generateSynchronousTree(null, null, maxnodes);
    }
    
    
    /**
     * Expand the given nodes into a synchronous tree. 
     * @param sroot source root
     * @param troot target root
     * @param maxnodes the maximal number of nodes in the tree
     * @return the number of generated nodes
     */
    public int generateSynchronousTree(NodeID sroot, NodeID troot, int maxnodes) {
        // Determine number of strongly connected components in the tree
        int sccs = randomChoice(choiceSCCinSynchronous);
        
        // Process each SCC
        for (int scc = 1; scc <= sccs; ++scc) {
            // Determine number of source and target nodes in scc
            int snodes = randomChoice(choiceNodesInScc);
            int tnodes = randomChoice(choiceNodesInScc);
            
            
        }
        return 0;
        
        // 1. Create a random tree of translation units
        // 2. For each translation unit, create a set of strongly connected components
        // 3. For each scc, divide nodes into source and target nodes (s-scc, t-scc)
        // 4. Create cycle that goes through all nodes in scc
    }
    
    int randomChoice(double[] probs) {
        double rand = random.nextDouble();
        double sum = 0;
        int i = -1;
        while (sum < rand && i < probs.length) {
            sum += probs[++i];
        }
        return (i<0) ? 0 : i;
    }
    
}
